home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 February: Technology Seed / Mac Tech Seed Feb '97.toast / OpenDoc 1.2b2c1 / Implementation / Storage / Bento / FileCtr.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1997-02-13  |  13.1 KB  |  479 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        FileCtr.cpp
  3.  
  4.     Contains:    Implementation of ODFileContainer class.
  5.  
  6.     Owned by:    Vincent Lo
  7.  
  8.     Copyright:    © 1993 - 1996 by Apple Computer, Inc., all rights reserved.
  9.  
  10.     Change History (most recent first):
  11.  
  12.          <8>     9/27/96    EL        1353486: document may become write
  13.                                     protected after opening.
  14.          <7>     8/13/96    DM        1376080: TempSuppressFatalBentoError
  15.                                     spelling
  16.          <6>     5/24/96    jpa        1246074: SOM_CATCH --> SOM_TRY..SOM_ENDTRY
  17.          <4>     5/23/96    DH        1344338: Force quit of document when
  18.                                     dragging 'Bad' file or Container. Turned
  19.                                     off fatal Bento errors for Open and Create
  20.                                     container operations.1333189: When a drag
  21.                                     of an OpenDoc document fails, document is
  22.                                     left open. If document fails to open, manually
  23.                                     close the file.
  24.          <2>     1/15/96    TJ        Cleaned Up
  25.     In Progress:
  26.         
  27. */
  28.  
  29. #define ODFileContainer_Class_Source
  30.  
  31. #define VARIABLE_MACROS
  32.  
  33. #include <FileCtr.xih>
  34.  
  35. #ifndef _PLFMDEF_
  36. #include "PlfmDef.h"
  37. #endif
  38.  
  39. #ifndef _BENTODEF_
  40. #include "BentoDef.h"
  41. #endif
  42.  
  43. #ifndef SOM_ODStorageSystem_xh
  44. #include <ODStor.xh>
  45. #endif
  46.  
  47. #ifndef _FSHDR_
  48. #include "FSHdr.h"
  49. #endif
  50.  
  51. #ifndef _TARGTHDR_
  52. #include "TargtHdr.h"
  53. #endif
  54.  
  55. #ifndef _INDHDR_
  56. #include "IndHdr.h"
  57. #endif
  58.  
  59. #ifndef __CM_API__
  60. #include "CMAPI.h"
  61. #endif
  62.  
  63. #ifndef _EXCEPT_
  64. #include "Except.h"
  65. #endif
  66.  
  67. #ifndef SOM_Module_OpenDoc_Errors_defined
  68. #include "ErrorDef.xh"
  69. #endif
  70.  
  71. #ifndef _ODNEW_
  72. #include <ODNew.h>
  73. #endif
  74.  
  75. #ifndef _PLFMFILE_
  76. #include <PlfmFile.h>
  77. #endif
  78.  
  79. #ifndef _STORUTIL_
  80. #include <StorUtil.h>
  81. #endif
  82.  
  83. #ifndef _ITEXT_
  84. #include <IText.h>
  85. #endif
  86.  
  87. #ifndef _BARRAY_
  88. #include <BArray.h>
  89. #endif
  90.  
  91. #ifndef __ALIASES__
  92. #include <Aliases.h>
  93. #endif
  94.  
  95. #ifdef DebugRefCount
  96. #include "Stdio.h"
  97. #endif
  98.  
  99. #ifndef _BENTOSUPPRESS_
  100. #include <BentoSuppress.h>
  101. #endif
  102.  
  103. #if ODDebug
  104. // #define ODDebug_ODFileContainer 1
  105. #endif
  106.  
  107. #pragma segment ODFileContainer
  108.  
  109. //==============================================================================
  110. // ODFileContainer
  111. //==============================================================================
  112.  
  113. //------------------------------------------------------------------------------
  114. // ODFileContainer: ~ODFileContainer
  115. //------------------------------------------------------------------------------
  116.  
  117. SOM_Scope void  SOMLINK ODFileContainersomUninit(ODFileContainer *somSelf)
  118. {
  119.     ODFileContainerData *somThis = ODFileContainerGetData(somSelf);
  120.     ODFileContainerMethodDebug("ODFileContainer","somUninit");
  121.  
  122. #ifdef DebugRefCount
  123.     printf("~ODFileContainer %x CMContainer %x RefCount %d\n", somSelf, _fCMContainer, _fRefCount);
  124.     fflush(stdout);
  125. #endif
  126.  
  127.     TRY{
  128.         Environment *ev = somGetGlobalEnvironment ();
  129.     
  130.         if (_fCMContainer != kODNULL)
  131.             somSelf->Close(ev);
  132.     
  133.         if (_fHandlers != kODNULL)
  134.             delete _fHandlers;
  135.     
  136.         if (_fPlatformFile != kODNULL)
  137.             delete _fPlatformFile;
  138.             
  139.         if (_fAlias != kODNULL)
  140.             ODDisposeHandle((ODHandle) _fAlias);
  141.     }CATCH_ALL{
  142.         // Ignore exceptions
  143.     }ENDTRY
  144. }
  145.  
  146. //------------------------------------------------------------------------------
  147. // ODFileContainer: InitContainer
  148. //------------------------------------------------------------------------------
  149.  
  150. SOM_Scope void  SOMLINK ODFileContainerInitContainer(ODFileContainer *somSelf, Environment *ev,
  151.         ODStorageSystem* storage, ODContainerID* id)
  152. {
  153.     ODFileContainerData *somThis = ODFileContainerGetData(somSelf);
  154.     ODFileContainerMethodDebug("ODFileContainer","InitContainer");
  155.     
  156.     SOM_TRY
  157.  
  158.     /* Moved from somInit. SOM itself sets fields to zero
  159.     _fCMContainer = kODNULL;
  160.     _fHandlers = kODNULL;
  161.     _fAlias = kODNULL;
  162.     _fPlatformFile = kODNULL;
  163.     */
  164.     
  165.     OSErr err = NewAlias(kODNULL, (FSSpec*) id->_buffer, &_fAlias);
  166.     if (err != noErr)
  167.         THROW(kODErrCannotCreateContainer);
  168.  
  169.     // Change id to exclude any garbage before FSSpec.name.
  170.     // struct FSSpec {
  171.     //     short                            vRefNum;
  172.     //     long                            parID;
  173.     //     Str63                            name;
  174.     // };
  175.     id->_length = sizeof(short) + sizeof(long) + ((FSSpec*) id->_buffer)->name[0] + 1;
  176.     
  177.     // Call parent with the updated id
  178.     parent_InitContainer(somSelf, ev, storage, id);
  179.     
  180.     _fPlatformFile = new PlatformFile();
  181.     _fPlatformFile->Specify((ODFileSpec*) id->_buffer);
  182.         
  183.     _fHandlers = new(somSelf->GetHeap(ev)) ODFSBentoHandlers(somSelf->GetCMSession(ev),
  184.                                                             _fPlatformFile);
  185.     _fHandlers->Initialize();
  186.  
  187.     SOM_CATCH_ALL
  188.     SOM_ENDTRY
  189. }
  190.  
  191. //------------------------------------------------------------------------------
  192. // ODFileContainer: GetID
  193. //------------------------------------------------------------------------------
  194.  
  195. SOM_Scope ODContainerID  SOMLINK ODFileContainerGetID(ODFileContainer *somSelf, Environment *ev)
  196. {
  197.     ODFileContainerData *somThis = ODFileContainerGetData(somSelf);
  198.     ODFileContainerMethodDebug("ODFileContainer","GetName");
  199.     
  200.     ODByteArray ba;
  201.  
  202.     SOM_TRY
  203.     
  204.     ODBoolean    dummyWasChanged;
  205.     ODFileSpec*    fsSpec = (ODFileSpec*) ODNewPtrClear(sizeof(ODFileSpec));
  206.     
  207.     OSErr err = ResolveAlias(kODNULL, _fAlias, fsSpec, &dummyWasChanged);
  208.     if (err != noErr) {
  209.         *fsSpec = _fPlatformFile->GetFileSpec();
  210.     }
  211.     ba._buffer = (octet*) fsSpec;
  212.     ba._maximum = sizeof(ODFileSpec);
  213.     ba._length = sizeof(short) + sizeof(long) + ((FSSpec*) ba._buffer)->name[0] + 1;
  214.     
  215.     SOM_CATCH_ALL
  216.         ba._buffer = kODNULL;
  217.         ba._maximum = ba._length = 0;
  218.     SOM_ENDTRY
  219.     
  220.     return ba;
  221. }
  222.  
  223. //------------------------------------------------------------------------------
  224. // ODFileContainer: GetName
  225. //------------------------------------------------------------------------------
  226.  
  227. SOM_Scope ODContainerName  SOMLINK ODFileContainerGetName(ODFileContainer *somSelf, Environment *ev)
  228. {
  229.     ODFileContainerData *somThis = ODFileContainerGetData(somSelf);
  230.     ODFileContainerMethodDebug("ODFileContainer","GetName");
  231.  
  232.     ODFileSpec            fsSpec;
  233.     ODContainerName*    name = kODNULL;
  234.     ODBoolean            dummyWasChanged;
  235.     
  236.     SOM_TRY
  237.     
  238.     OSErr err = ResolveAlias(kODNULL, _fAlias, &fsSpec, &dummyWasChanged);
  239.     if (err != noErr) {
  240.         name = _fPlatformFile->GetName();
  241.     }
  242.     else {
  243.         name = CreateIText(0, 0, (StringPtr) &fsSpec.name);
  244.     }
  245.     
  246.     SOM_CATCH_ALL
  247.     SOM_ENDTRY
  248.     
  249.     return *name;    
  250. }
  251.  
  252. //------------------------------------------------------------------------------
  253. // ODFileContainer: SetName
  254. //------------------------------------------------------------------------------
  255.  
  256. SOM_Scope void  SOMLINK ODFileContainerSetName(ODFileContainer *somSelf, Environment *ev,
  257.         ODContainerName* name)
  258. {
  259.     ODFileContainerData *somThis = ODFileContainerGetData(somSelf);
  260.     ODFileContainerMethodDebug("ODFileContainer","SetName");
  261.  
  262.     SOM_TRY
  263.     
  264.     StringPtr fileName = GetPStringFromIText(name);
  265.     _fPlatformFile->Rename(fileName);
  266.  
  267.     SOM_CATCH_ALL
  268.     SOM_ENDTRY
  269. }
  270.  
  271. //------------------------------------------------------------------------------
  272. // ODFileContainer: Create
  273. //------------------------------------------------------------------------------
  274.  
  275. SOM_Scope ODContainer*  SOMLINK ODFileContainerCreate(ODFileContainer *somSelf, Environment *ev)
  276. {
  277.     ODFileContainerData *somThis = ODFileContainerGetData(somSelf);
  278.     ODFileContainerMethodDebug("ODFileContainer","Create");
  279.  
  280.     SOM_TRY
  281.  
  282.     if (_fCMContainer == kODNULL) {
  283.     
  284.         somSelf->SetModDate(ev, _fPlatformFile->GetFileModDate());
  285.  
  286.         CMSession cmSession = somSelf->GetCMSession(ev);
  287.  
  288.         CMSetMetaHandler(cmSession,
  289.                         (CMGlobalName)CMTargetHandlersTypeName,
  290.                         targetContainerMetahandler);
  291.  
  292.         {    
  293.             TempSuppressFatalBentoError temp;
  294.                 
  295.             _fCMContainer = CMOpenNewContainer(cmSession,
  296.                                             _fHandlers,
  297.                                             (CMGlobalName) kODBentoFileTypeName,
  298.                                             (CMContainerUseMode) (kCMWriting),
  299.                                             1, kCMDefaultEndian);
  300.         }
  301.         if (_fCMContainer == kODNULL)
  302.             THROW(kODErrCannotCreateContainer);
  303.     }
  304.  
  305.     return somSelf;
  306.  
  307.     SOM_CATCH_ALL
  308.     SOM_ENDTRY
  309.     return somSelf;
  310. }
  311.  
  312. //------------------------------------------------------------------------------
  313. // ODFileContainer: Open
  314. //------------------------------------------------------------------------------
  315.  
  316. SOM_Scope ODContainer*  SOMLINK ODFileContainerOpen(ODFileContainer *somSelf, Environment *ev)
  317. {
  318.     ODFileContainerData *somThis = ODFileContainerGetData(somSelf);
  319.     ODFileContainerMethodDebug("ODFileContainer","Open");
  320.  
  321.     SOM_TRY
  322.  
  323.     if (_fCMContainer == kODNULL) {
  324.     
  325.         somSelf->SetModDate(ev, _fPlatformFile->GetFileModDate());
  326.  
  327.         CMSession cmSession = somSelf->GetCMSession(ev);
  328.         
  329.         CMSetMetaHandler(cmSession,
  330.                         (CMGlobalName)CMTargetHandlersTypeName,
  331.                         targetContainerMetahandler);
  332.         {    // Suppress fatal Bento errors.
  333.             TempSuppressFatalBentoError temp;
  334.                                 
  335.             TRY
  336.                 _fCMContainer = CMOpenContainer(cmSession,
  337.                                                 _fHandlers,
  338.                                                 (CMGlobalName) kODBentoFileTypeName,
  339.                                                 (CMContainerUseMode) kCMReuseFreeSpace);
  340.             CATCH_ALL
  341.                 // At this point there was some problem with opening the Container.
  342.                 // Unfortunately, Bento will not cleanup after determining there is a
  343.                 // problem, which leaves the file open in the file system. We must 
  344.                 // close it manually then.
  345.                 _fPlatformFile->Close();
  346.                 return kODNULL;   // Propogate the error by not clearing it here and
  347.                                   // immediately exiting.
  348.             ENDTRY
  349.         }    
  350.         if (_fCMContainer == kODNULL)
  351.             THROW(kODErrCannotOpenContainer);
  352.     }
  353.  
  354.     return somSelf;
  355.  
  356.     SOM_CATCH_ALL
  357.     SOM_ENDTRY
  358.     return somSelf;
  359. }
  360.  
  361. //------------------------------------------------------------------------------
  362. // ODFileContainer: Close
  363. //------------------------------------------------------------------------------
  364.  
  365. SOM_Scope ODContainer*  SOMLINK ODFileContainerClose(ODFileContainer *somSelf, Environment *ev)
  366. {
  367.     ODFileContainerData *somThis = ODFileContainerGetData(somSelf);
  368.     ODFileContainerMethodDebug("ODFileContainer","Close");
  369.  
  370.     SOM_TRY
  371.  
  372.     if (_fCMContainer != kODNULL) {
  373.         SOM_TRY
  374.             // get a new copy of PlatformFile because fileSpec may have changed
  375.             TempPlatformFile tempfile = GetPlatformFileFromContainer(ev, somSelf);
  376.             ODBoolean locked = tempfile->IsLocked();
  377.             // abort if there is no change or file is locked
  378.             if ((somSelf->GetDirtyFlag(ev) != kODFalse) && (locked == kODFalse)) {
  379.                 CMObject    currObj, nextObj;
  380.                 CMProperty    embedProp;
  381.                 CMType        embedType;
  382.                 CMValue        currValue;
  383.                 CMSize        valueSize;
  384.     
  385.                 embedProp = CMRegisterProperty(_fCMContainer, kODPropVersionList);
  386.                 currObj = CMGetNextObjectWithProperty(_fCMContainer, kODNULL, embedProp);
  387.                 CMKeepObject(currObj);
  388.                 embedProp = CMRegisterProperty(_fCMContainer, kODEmbeddedContainerProperty); // "OpenDoc:EmbeddedContainer"
  389.                 embedType = CMRegisterType(_fCMContainer, kODEmbeddedContainerType); // "OpenDoc:EmbeddedContainerType"
  390.                 currObj = CMGetNextObjectWithProperty(_fCMContainer, kODNULL, embedProp);
  391.                 while (currObj) {
  392.                     nextObj = CMGetNextObjectWithProperty(_fCMContainer, currObj, embedProp);
  393.                     currValue = CMUseValue(currObj, embedProp, embedType);
  394.                     if (currValue) {
  395.                         valueSize =  CMGetValueSize(currValue);
  396.                         CMReleaseValue(currValue);
  397.                         if (valueSize)    /* no need to keep it unless length is not zero */
  398.                             CMKeepObject(currObj);
  399.                     } 
  400.                     currObj = nextObj;
  401.                 };
  402.                 CMCloseContainer(_fCMContainer);
  403. #if ODDebug_ODFileContainer
  404. somPrintf("FileContainer Close: Close\n");
  405. #endif
  406.             }
  407.             else {
  408.                 CMAbortContainer(_fCMContainer);
  409. #if ODDebug_ODFileContainer
  410. somPrintf("FileContainer Close: Abort\n");
  411. #endif
  412.             }
  413.             tempfile->SetFileModDate(somSelf->GetModDate(ev));
  414.         SOM_CATCH_ALL
  415.             if (ErrorCode() == kODErrBentoErr)
  416.                 SetErrorCode(kODErrFatalContainerError);
  417.         SOM_ENDTRY
  418.         _fCMContainer = kODNULL;
  419.     }
  420.     
  421.     return ODFileContainer_parent_ODBentoContainer_Close(somSelf, ev);
  422.  
  423.     SOM_CATCH_ALL
  424.     SOM_ENDTRY
  425.     return somSelf;
  426. }
  427.  
  428. //------------------------------------------------------------------------------
  429. // ODFileContainer: Purge
  430. //------------------------------------------------------------------------------
  431.  
  432. SOM_Scope ODSize  SOMLINK ODFileContainerPurge(ODFileContainer *somSelf, Environment *ev,
  433.         ODSize size)
  434. {
  435.     ODFileContainerData *somThis = ODFileContainerGetData(somSelf);
  436.     ODFileContainerMethodDebug("ODFileContainer","Purge");
  437.  
  438.     ODSize freed = 0;    ODVolatile(freed);
  439.  
  440.     SOM_TRY
  441.          freed = parent_Purge(somSelf, ev, size);
  442.     SOM_CATCH_ALL
  443.         WARN("Error %ld trying to purge in ODFileContainerPurge",ErrorCode());
  444.         SetErrorCode(kODNoError);        // dh - Eat the exception; Purge should not 
  445.                                         // propagate it because clients function
  446.                                         // fine whether memory was purged or not.
  447.                                         // Also, don't return 0 if an exception
  448.                                         // was thrown. Initialized counter should
  449.                                         // suffice to give correct return value.
  450.     SOM_ENDTRY
  451.     
  452.     return freed;
  453. }
  454.  
  455. //------------------------------------------------------------------------------
  456. // ODFileContainer: GetCMContainer
  457. //------------------------------------------------------------------------------
  458.  
  459. SOM_Scope CMContainer  SOMLINK ODFileContainerGetCMContainer(ODFileContainer *somSelf, Environment *ev)
  460. {
  461.     ODFileContainerData *somThis = ODFileContainerGetData(somSelf);
  462.     ODFileContainerMethodDebug("ODFileContainer","GetCMContainer");
  463.  
  464.     return _fCMContainer;
  465. }
  466.  
  467. //------------------------------------------------------------------------------
  468. // ODFileContainer: GetHandlers
  469. //------------------------------------------------------------------------------
  470.  
  471. SOM_Scope ODBentoHandlers*  SOMLINK ODFileContainerGetHandlers(ODFileContainer *somSelf, Environment *ev)
  472. {
  473.     ODFileContainerData *somThis = ODFileContainerGetData(somSelf);
  474.     ODFileContainerMethodDebug("ODFileContainer","GetHandlers");
  475.  
  476.     return _fHandlers;
  477. }
  478.  
  479.